﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Event;
using YooAsset;
using System.IO;

public class Boot1 : MonoBehaviour
{
    /// <summary>
    /// 资源系统运行模式
    /// </summary>
    public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;

    void Awake()
    {
        Debug.Log($"资源系统运行模式：{PlayMode}");
        Application.targetFrameRate = 60;
        Application.runInBackground = true;
        DontDestroyOnLoad(this.gameObject);
    }
    IEnumerator Start()
    {
        // 游戏管理器
        //GameManager.Instance.Behaviour = this;

        //// 初始化事件系统
        //UniEvent.Initalize();

        //// 初始化资源系统
        //YooAssets.Initialize();

        //// 加载更新页面
        //var go = Resources.Load<GameObject>("PatchWindow");
        //GameObject.Instantiate(go);

        //// 开始补丁更新流程
        //PatchOperation operation = new PatchOperation("DefaultPackage", EDefaultBuildPipeline.BuiltinBuildPipeline.ToString(), PlayMode);
        //YooAssets.StartOperation(operation);
        //yield return operation;

        //// 设置默认的资源包
        //var gamePackage = YooAssets.GetPackage("DefaultPackage");
        //YooAssets.SetDefaultPackage(gamePackage);

        // 切换到主页面场景
        //SceneEventDefine.ChangeToHomeScene.SendEventMessage();

        yield return null;
        // 初始化资源系统
        YooAssets.Initialize();
       // yield return StartPrefab();
        StartCoroutine(StartFile());
        // 创建默认的资源包


    }
    /// <summary>
    /// 加载其他资源
    /// </summary>
    /// <returns></returns>
    IEnumerator StartPrefab()
    {
        var package = YooAssets.CreatePackage("DefaultPackage");

        // 设置该资源包为默认的资源包，可以使用YooAssets相关加载接口加载该资源包内容。
        YooAssets.SetDefaultPackage(package);

        if (PlayMode == EPlayMode.EditorSimulateMode)
        {
            var initParameters = new EditorSimulateModeParameters();
            initParameters.SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(EDefaultBuildPipeline.BuiltinBuildPipeline.ToString(), "DefaultPackage");
            yield return package.InitializeAsync(initParameters);
        }
        else if (PlayMode == EPlayMode.OfflinePlayMode)
        {

        }
        else if (PlayMode == EPlayMode.HostPlayMode)
        {
            string defaultHostServer = "http://127.0.0.1/CDN/Demo/v2.0";
            string fallbackHostServer = "http://127.0.0.1/CDN/Demo/v2.0";
            var initParameters = new HostPlayModeParameters();
            initParameters.DecryptionServices = new FileStreamDecryption();
            initParameters.BuildinQueryServices = new GameQueryServices(); //太空战机DEMO的脚本类，详细见StreamingAssetsHelper

            initParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            var initOperation = package.InitializeAsync(initParameters);
            yield return initOperation;

            if (initOperation.Status == EOperationStatus.Succeed)
            {
                Debug.Log("web资源包初始化不成功！");
                Debug.LogError($"资源包初始化失败：{initOperation.Error}");
            }

        }
        else if (PlayMode == EPlayMode.WebPlayMode)
        {
            string defaultHostServer = "http://127.0.0.1/CDN/DemoWeb/v2.0";
            string fallbackHostServer = "http://127.0.0.1/CDN/DemoWeb/v2.0";
            var createParameters = new WebPlayModeParameters();
            createParameters.DecryptionServices = new FileStreamDecryption();
            createParameters.BuildinQueryServices = new GameQueryServices();
            createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            var initOperation = package.InitializeAsync(createParameters);
            yield return initOperation;

            if (initOperation.Status == EOperationStatus.Succeed)
            {
                
                Debug.LogError($"web资源包初始化失败：{initOperation.Error}");
            }
            Debug.Log("web资源包初始化成功！");
            
        }
        Debug.Log("web资源包初始化成功！");
        yield return UpdatePackageVersion(package);
        StartCoroutine(LoadScene(package));
    }

    IEnumerator StartFile()
    {
        var package = YooAssets.CreatePackage("DefaultPackage");

        // 设置该资源包为默认的资源包，可以使用YooAssets相关加载接口加载该资源包内容。
        YooAssets.SetDefaultPackage(package);

        if (PlayMode == EPlayMode.EditorSimulateMode)
        {
            var initParameters = new EditorSimulateModeParameters();
            initParameters.SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(EDefaultBuildPipeline.BuiltinBuildPipeline.ToString(), "DefaultPackage");
            yield return package.InitializeAsync(initParameters);
        }
        else if (PlayMode == EPlayMode.OfflinePlayMode)
        {

        }
        else if (PlayMode == EPlayMode.HostPlayMode)
        {
            string defaultHostServer = "http://127.0.0.1/CDN/Android/v1.0";
            string fallbackHostServer = "http://127.0.0.1/CDN/Android/v1.0";
            var initParameters = new HostPlayModeParameters();
            initParameters.DecryptionServices = new FileStreamDecryption();
            initParameters.BuildinQueryServices = new GameQueryServices(); //太空战机DEMO的脚本类，详细见StreamingAssetsHelper

            initParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            var initOperation = package.InitializeAsync(initParameters);
            yield return initOperation;

            if (initOperation.Status != EOperationStatus.Succeed)
            {
                Debug.LogError($"资源包初始化失败：{initOperation.Error}");
            }

        }
        else if (PlayMode == EPlayMode.WebPlayMode)
        {
            string defaultHostServer = "http://127.0.0.1/CDN/Android/v1.0";
            string fallbackHostServer = "http://127.0.0.1/CDN/Android/v1.0";
            var createParameters = new WebPlayModeParameters();
            createParameters.DecryptionServices = new FileStreamDecryption();
            createParameters.BuildinQueryServices = new GameQueryServices();
            createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            var initOperation = package.InitializeAsync(createParameters);
            yield return initOperation;

            if (initOperation.Status != EOperationStatus.Succeed)
            {
                Debug.LogError($"web资源包初始化失败：{initOperation.Error}");
            }
        }
        Debug.Log("web配置文件初始化成功！");
        yield return UpdatePackageVersion(package);
        StartCoroutine(LoadScene(package));
        //string location = "Assets/GameRes/wwise/init.bnk";
        //RawFileHandle handle = package.LoadRawFileAsync("RawFile");
        //yield return handle;
        ////byte[] fileData = handle.GetRawFileData();
        //string fileText = handle.GetRawFileText();
        ////string filePath = handle.GetRawFilePath();
        //Debug.Log("fileText========" + fileText);
    }


    /// <summary>
    /// 获取资源版本号
    /// </summary>
    /// <returns></returns>
    private IEnumerator UpdatePackageVersion(ResourcePackage package)
    {

        Debug.Log("获取资源版本号！");
        var operation = package.UpdatePackageVersionAsync();
        yield return operation;

        if (operation.Status == EOperationStatus.Succeed)
        {
            //更新成功
            string packageVersion = operation.PackageVersion;
            Debug.Log($"Updated package Version : {packageVersion}");
            //拿到版本号之后  用版本号获取补丁版本
            StartCoroutine(UpdatePackageManifest(packageVersion, package));
        }
        else
        {
            //更新失败
            Debug.LogError(operation.Error);
        }
    }
    /// <summary>
	///获取补丁版本
	/// </summary>
	/// <param name="packageVersion"></param>
	/// <returns></returns>
	private IEnumerator UpdatePackageManifest(string packageVersion, ResourcePackage package)
    {
        Debug.Log("获取补丁版本！");
        // 更新成功后自动保存版本号，作为下次初始化的版本。
        // 也可以通过operation.SavePackageVersion()方法保存。
        bool savePackageVersion = true;
        var operation = package.UpdatePackageManifestAsync(packageVersion, savePackageVersion);
        yield return operation;

        if (operation.Status != EOperationStatus.Succeed)
        {
            //更新失败
            Debug.LogError(operation.Error);
            yield break;
        }
        yield return Download(package);
       

        //string location = "Assets/GameRes/wwise/init.bnk";
        //RawFileHandle handle = package.LoadRawFileAsync("RawFile");
        //yield return handle;
        ////byte[] fileData = handle.GetRawFileData();
        //string fileText = handle.GetRawFileText();
        ////string filePath = handle.GetRawFilePath();
        //Debug.Log("fileText========" + fileText);

    }
    IEnumerator LoadScene(ResourcePackage package)
    {
        string location = "scene_home";
        var sceneMode = UnityEngine.SceneManagement.LoadSceneMode.Single;
        bool suspendLoad = false;
        SceneHandle handle = package.LoadSceneAsync(location, sceneMode, suspendLoad);
        yield return handle;
        Debug.Log($"Scene name is {handle.SceneName}");
    }
    IEnumerator LoadPrefab(ResourcePackage package)
    {
        AssetHandle handle = package.LoadAssetAsync<GameObject>("Assets/GameRes/Panel/login.prefab");
        yield return handle;
        GameObject go = handle.InstantiateSync();
        Debug.Log($"Prefab name is {go.name}");
    }
    /// <summary>
    /// 开始下载资源
    /// </summary>
    /// <param name="package"></param>
    /// <returns></returns>
    IEnumerator Download(ResourcePackage package)
    {
        Debug.Log("xiazia ！");
        int downloadingMaxNum = 10;
        int failedTryAgain = 3;

        var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);

        Debug.Log("需要下载的资源 ！==" + downloader.TotalDownloadCount);
        //没有需要下载的资源
        if (downloader.TotalDownloadCount == 0)
        {
            yield break;
        }

        //需要下载的文件总数和总大小
        int totalDownloadCount = downloader.TotalDownloadCount;
        long totalDownloadBytes = downloader.TotalDownloadBytes;

        //注册回调方法
        downloader.OnDownloadErrorCallback = OnDownloadErrorFunction;
        downloader.OnDownloadProgressCallback = OnDownloadProgressUpdateFunction;
        downloader.OnDownloadOverCallback = OnDownloadOverFunction;
        downloader.OnStartDownloadFileCallback = OnStartDownloadFileFunction;

        //开启下载
        downloader.BeginDownload();
        yield return downloader;

        //检测下载结果
        if (downloader.Status == EOperationStatus.Succeed)
        {
            //下载成功
        }
        else
        {
            //下载失败
        }


    }
    /// <summary>
	/// 更新中
	/// </summary>
	/// <param name="totalDownloadCount"></param>
	/// <param name="currentDownloadCount"></param>
	/// <param name="totalDownloadBytes"></param>
	/// <param name="currentDownloadBytes"></param>
	private void OnDownloadProgressUpdateFunction(int totalDownloadCount, int currentDownloadCount, long totalDownloadBytes, long currentDownloadBytes)
    {
        Debug.Log(string.Format("文件总数：{0}，已下载文件数量{1}，下载总大小：{2}，已下载大小：{3}", totalDownloadCount, currentDownloadCount, totalDownloadBytes, currentDownloadBytes));
    }
    /// <summary>
    /// 开始下载文件
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="sizeBytes"></param>
    private void OnStartDownloadFileFunction(string fileName, long sizeBytes)
    {
        Debug.Log(string.Format("下载文件：{0}，大小{1}", fileName, sizeBytes));
    }

    /// <summary>
    /// 下载完成
    /// </summary>
    /// <param name="isSucceed"></param>
    private void OnDownloadOverFunction(bool isSucceed)
    {
        Debug.Log(string.Format("下载完成：{0}", isSucceed));
    }
    /// <summary>
    /// 下载错误
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="error"></param>
    private void OnDownloadErrorFunction(string fileName, string error)
    {
        throw new NotImplementedException();
    }
    /// <summary>
	/// 远端资源地址查询服务类
	/// </summary>
	private class RemoteServices : IRemoteServices
    {
        private readonly string _defaultHostServer;
        private readonly string _fallbackHostServer;

        public RemoteServices(string defaultHostServer, string fallbackHostServer)
        {
            _defaultHostServer = defaultHostServer;
            _fallbackHostServer = fallbackHostServer;
        }
        string IRemoteServices.GetRemoteMainURL(string fileName)
        {
            return $"{_defaultHostServer}/{fileName}";
        }
        string IRemoteServices.GetRemoteFallbackURL(string fileName)
        {
            return $"{_fallbackHostServer}/{fileName}";
        }
    }
    /// <summary>
	/// 资源文件流加载解密类
	/// </summary>
	private class FileStreamDecryption : IDecryptionServices
    {
        /// <summary>
        /// 同步方式获取解密的资源包对象
        /// 注意：加载流对象在资源包对象释放的时候会自动释放
        /// </summary>
        AssetBundle IDecryptionServices.LoadAssetBundle(DecryptFileInfo fileInfo, out Stream managedStream)
        {
            BundleStream bundleStream = new BundleStream(fileInfo.FileLoadPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            managedStream = bundleStream;
            return AssetBundle.LoadFromStream(bundleStream, fileInfo.ConentCRC, GetManagedReadBufferSize());
        }

        /// <summary>
        /// 异步方式获取解密的资源包对象
        /// 注意：加载流对象在资源包对象释放的时候会自动释放
        /// </summary>
        AssetBundleCreateRequest IDecryptionServices.LoadAssetBundleAsync(DecryptFileInfo fileInfo, out Stream managedStream)
        {
            BundleStream bundleStream = new BundleStream(fileInfo.FileLoadPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            managedStream = bundleStream;
            return AssetBundle.LoadFromStreamAsync(bundleStream, fileInfo.ConentCRC, GetManagedReadBufferSize());
        }

        private static uint GetManagedReadBufferSize()
        {
            return 1024;
        }
    }
    //private class RemoteServices : IRemoteServices
    //{
    //    public bool GetRemoteMainURL(string fileName)
    //    {
    //        string buildinFolderName = YooAssets.get();
    //        return BetterStreamingAssets.FileExists($"{buildinFolderName}/{fileName}");
    //    }
    //}
    //public interface RemoteServices
    //{
    //    string GetRemoteMainURL(string fileName);

    //    string GetRemoteFallbackURL(string fileName);
    //}
    // 文件解密的示例代码
    // 注意：解密类必须配合加密类。
    private class GameDecryptionServices : IDecryptionServices
    {
        public ulong LoadFromFileOffset(DecryptFileInfo fileInfo)
        {
            return 32;
        }

        public byte[] LoadFromMemory(DecryptFileInfo fileInfo)
        {
            // 如果没有内存加密方式，可以返回空
            throw new NotImplementedException();
        }

        public Stream LoadFromStream(DecryptFileInfo fileInfo)
        {
            // 如果没有流加密方式，可以返回空
            throw new NotImplementedException();
        }

        public uint GetManagedReadBufferSize()
        {
            return 1024;
        }

        public AssetBundle LoadAssetBundle(DecryptFileInfo fileInfo, out Stream managedStream)
        {
            throw new NotImplementedException();
        }

        public AssetBundleCreateRequest LoadAssetBundleAsync(DecryptFileInfo fileInfo, out Stream managedStream)
        {
            throw new NotImplementedException();
        }
    }
}